﻿using System;
//using System.Collections.Generic;
//using System.Text;

namespace Stauffware.Common.Core
{
	/// <summary>
	/// Generic interface for the result of parsing a string into some data type.
	/// Each result is in one of three possible states, represented by the
	/// boolean properties GotValue, IsError and IsEmpty.
	/// </summary>

	public interface IParse 
	{
		/// <summary>
		/// Returns whether or not the parse produced a (non-empty) value.  
		/// Exactly one of GotValue, IsError and IsEmpty will be true.
		/// </summary>
		bool GotValue { get; }

		/// <summary>
		/// Returns whether or not an error was detected during parsing.
		/// The lack of any value at all (i.e. an empty string) is not considered an error.
		/// Exactly one of GotValue, IsError and IsEmpty will be true.
		/// </summary>
		bool IsError { get; }

		/// <summary>
		/// Returns true if the parse operation found no value at all (either good or bad).
		/// Exactly one of GotValue, IsError and IsEmpty will be true.
		/// </summary>
		bool IsEmpty { get; }

		/// <summary>
		/// Returns an error message suitable for displaying to users,
		/// or null if there was no error.
		/// </summary>
		/// <remarks>
		/// If IsError is true, it returns a detailed description of the problem.
		/// If IsEmpty is true, it returns something like "expecting a T".
		/// If GotValue is true, it returns null.
		/// </remarks>
		string ErrorMessage { get; }

		/// <summary>
		/// Returns all the text that was parsed before determining the result.
		/// </summary>
		/// <remarks>
		/// If the parse options specified parsing the entire input, 
		/// then the entire input is returned.  Otherwise ...
		/// If GotValue is true, the returned string includes leading whitespace 
		/// (if any) and the characters that were parsed to get the result.
		/// If IsError is true, the returned string contains the parsed input
		/// up to and including the character that triggered the error.
		/// If IsEmpty is true, the returned string contains, at most, any 
		/// whitespace that was ignored before detecting the absence of a value.
		/// </remarks>
		string ParsedText { get; }

		/// <summary>
		/// Returns an exception containing the error information,
		/// or null if there was no error.
		/// </summary>
		/// <remarks>
		/// This method exists to support implicit casting of a Parse to a 
		/// ParseException so that a ParseException can be used in a throw statement.
		/// </remarks>
		ParseException ToException ();
	}

	//#################################################################################
	/// <summary>
	/// Generic interface for the result of parsing a string into some data type.
	/// </summary>
	/// <typeparam name="T">the data type produced by the parse operation</typeparam>
	/// <remarks>
	/// In addition to this interface, implementors should also provide the following:
	/// 
	///		// Implicit conversion of a successful IParse to its result of type T.
	///		static implicit operator T (Parse&lt;T&gt; r);
	///		
	///		// Implicit conversion of an unsuccessful IParse to an exception,
	///		// so that an IParse can be used in a "throw" statement.
	///		static implicit operator Exception (Parse&lt;T&gt; r);
	/// 
	/// Byte parsing examples:
	///		"" -> empty; 0 chars parsed
	///		"   " (whitespace allowed) -> empty; 3 chars parsed
	///		"   " (whitespace not allowed) -> error; 1 char parsed
	///		"257" -> error; 0 chars parsed
	///		"0" -> success; 1 char parsed
	///		"123abc" (parsing partial input) -> success; 3 chars parsed
	///		"123abc" (parsing entire input) -> error; 4 chars parsed
	/// </remarks>

	public interface IParse<T> : IParse
	{
		/// <summary>
		/// Returns the parsed value.  Reading this property is valid only
		/// if GotValue is true (otherwise it fails an assertion).
		/// </summary>
		T Value { get; }

	}

	//#################################################################################
}
